﻿using FreeDream.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace FreeDream.WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TestAuthController : ControllerBase
    {
        private readonly IConfiguration _config;
        //private readonly AddressRepository _addressRepository;

        public TestAuthController(IConfiguration config)
        {
            _config = config;
        }

        [HttpGet("Add")]
        public string Address()
        {
            //var res = _addressRepository.Add("ceshi");
            //Serilog.Log.Error($"Address...{DateTime.Now}");
            return DateTime.Now.ToString();
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("login")]
        public async Task<IActionResult> LoginAsync(LoginDto loginDto)
        {
            #region 校验用户信息，假设此处我们已经校验成功
            var userid = "123";
            var username = "admin";

            #endregion

            #region 签发JWT

            //生成一个刷新令牌
            var refreshtoken = Guid.NewGuid().ToString("N");

            var loginViewModel = new LoginViewModel
            {
                Expires = DateTime.Now.AddDays(30),
            };

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, userid),
                new Claim(ClaimTypes.Name, username)
            };
            var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_config["JwtSecurityKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: "net6api.com",
                audience: "net6api.com",
                claims: claims,
                expires: loginViewModel.Expires,
                signingCredentials: creds);
            //输出Token
            loginViewModel.AccessToken = new JwtSecurityTokenHandler().WriteToken(token);
            return Ok(loginViewModel);

            #endregion
        }

        [AllowAnonymous]
        [HttpPost("refresh")]
        public async Task<IActionResult> RefreshAsync(RefreshTokenDto dto)
        {
            try
            {
                var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(dto.AccessToken);
                var userid = jwtToken.Claims.FirstOrDefault(a => a.Type == ClaimTypes.NameIdentifier)?.Value;
                var username = jwtToken.Claims.FirstOrDefault(a => a.Type == ClaimTypes.Name)?.Value;
                var refreshtoken = "";// CacheHelper.Get<string>($"{"刷新令牌"}_{userid}");
                if (refreshtoken == null) return Ok("未找到该刷新令牌");
                if (refreshtoken != dto.RefreshToken) return Ok("刷新令牌不正确");
                #region 签发JWT
                //生成一个新的刷新令牌
                refreshtoken = Guid.NewGuid().ToString("N");
                //CacheHelper.Set($"{"刷新令牌"}_{userid}", refreshtoken, TimeSpan.FromDays(30));
                var view = new LoginViewModel
                {
                    Expires = DateTime.Now.AddDays(7),
                    RefreshToken = refreshtoken
                };
                var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_config["JwtSecurityKey"]));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var token = new JwtSecurityToken(
                    issuer: "net6api.com",
                    audience: "net6api.com",
                    claims: jwtToken.Claims,
                    expires: view.Expires,
                    signingCredentials: creds);
                view.AccessToken = new JwtSecurityTokenHandler().WriteToken(token);
                return Ok(view);
                #endregion
            }
            catch (Exception)
            {
                return Ok("访问令牌解析失败");
            }
        }
    }
}
